import debounce from 'lodash.debounce';

function scrollhandler(el, loadingCb) {
  return debounce(() => {
    const rectObj = el.getBoundingClientRect();
    if (rectObj.top - window.innerHeight <= 150) {
      loadingCb();
    }
  });
}
export default function asyncComponent({
  componentFactory, loading = 'div', loadingData = 'loading', errorComponent, rootMargin = '0px', retry = 2
}) {
  let resolveComponent;
  return () => ({
    component: new Promise(resolve => resolveComponent = resolve), // 需要加载的组件，是一个promise
    loading: { // 加载中
      mounted() {
        // console.log('_______asyncComponent mounted');
        if (typeof IntersectionObserver === 'undefined') {
          const loadingCb = () => {
            componentFactory().then(resolveComponent).catch(e => console.error(e));
          };
          window.addEventListener('scroll', scrollhandler(this.$el, loadingCb), true);
          return;
        }

        const observer = new IntersectionObserver(([entries]) => { // callback:目标元素(loading组件)的可见性变化时调用的回调函数
          // console.log('________entries', entries);
          if (!entries.isIntersecting) return;
          observer.unobserve(this.$el); // 停止观察

          let p = Promise.reject();
          for (let i = 0; i < retry; i++) {
            p = p.catch(componentFactory);
          }
          p.then(resolveComponent).catch(e => console.error(e));
        }, {
          root: null,
          rootMargin,
          threshold: [0]
        });

        observer.observe(this.$el); // 开始观察
      },
      render(h) {
        // return h(loading, loadingData);
        return h(loading);
      },
      beforeDestroyed() {
        console.log('beforeDestroyed');
      }
    },
    // error: errorComponent, // 出错时
    delay: 200, // 渲染加载中组件前的等待时间
    // timeout: 3000, // 最长等待时间，超出此事件则渲染错误组件，默认：Infinity
  });
}
